﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Xunit;
using YAPL.Language.SourceParser;
using YAPL.Language.Ast;
using YAPL.Language.SourceParser.XML;

namespace YAPL.Test.YAPL.Language.Parser.XML.NodeParsers {
	public class XmlFunctionCallParserTest : XmlNodeParserTest {

		[Fact]
		public void FunctionCallShouldHaveMethodAttribute() {
			var callNode = new XElement(XmlNames.FunctionCallExpression);
			Assert.Throws<ArgumentNullException>(() => _parser.ParseNode(callNode));
		}

		[Fact]
		public void MethodAttributeShouldNotBeEmpty() {
			var callNode = new XElement(XmlNames.FunctionCallExpression, new XAttribute(XmlNames.FunctionCallNameAttribute,""));
			Assert.Throws<ArgumentException>(() => _parser.ParseNode(callNode));
		}

		[Fact]
		public void CallWithoutArgumentsShouldBeParsedCorrectly() {
			var callNode = new XElement(XmlNames.FunctionCallExpression, new XAttribute(XmlNames.FunctionCallNameAttribute, "print"));
			var expr = _parser.ParseNode(callNode);
			Assert.IsType(typeof(FunctionCallExpression), expr);
			var functionCall = (FunctionCallExpression) expr;
			Assert.Equal("print", functionCall.MethodName);
			Assert.Empty(functionCall.Arguments);
		}

		[Fact]
		public void CallWithArgumentsShouldBeParsedCorrectly() {
			var callNode = new XElement(XmlNames.FunctionCallExpression, new XAttribute(XmlNames.FunctionCallNameAttribute, "print"),
				new XElement(XmlNames.ArgumentsExpression,
					new XElement(XmlNames.VariableExpression, new XAttribute(XmlNames.IdentifierNameAttribute, "a")),
					new XElement(XmlNames.ConstantExpression, new XAttribute(XmlNames.ConstantValueAttribute, "'hello'")))
				);
			var expr = _parser.ParseNode(callNode);
			Assert.IsType(typeof(FunctionCallExpression), expr);
			var functionCall = (FunctionCallExpression)expr;
			Assert.Equal("print", functionCall.MethodName);
			Assert.Equal(2, functionCall.Arguments.Count);
			var arg0 = functionCall.Arguments[0];
			var arg1 = functionCall.Arguments[1];
			Assert.IsType(typeof(VariableExpression), arg0);
			Assert.IsType(typeof(ConstantExpression), arg1);
		}
	}
}